﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SQLite;
using System.Diagnostics;
using System.Data;
using plust.Clases;

namespace plust.Persistencia
{
    class PersistenciaDB
    {
        private SqlLiteHandler _bd;
        private String sql;

        public PersistenciaDB()
        {
            this._bd = new SqlLiteHandler();
        }

        #region Factura

        /// <summary>
        /// Ingresa una factura a la bd.
        /// </summary>
        /// <param name="factura"></param>
        /// <returns></returns>
        public Boolean ingresarFactura(Factura factura)
        {
            this.sql = string.Empty;
            this.sql = "INSERT INTO plust_factura (fecha_emision,estado_pago,valor_neto,id_cliente) values ('";
            this.sql += factura.fecha_emision;
            this.sql += "','";
            this.sql += factura.estado_pago;
            this.sql += "',";
            this.sql += factura.valor_neto;
            this.sql += ",";
            this.sql += factura.id_cliente;
            this.sql += ")";

            try
            {
                this._bd.ejecutarSinRetorno(sql);
                //this.vincularVenta(factura.id_factura);
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return false;
            }
        }

        /// <summary>
        /// Actualiza una factura.
        /// </summary>
        /// <param name="factura"></param>
        /// <returns></returns>
        public bool actualizarFactura(Factura factura)
        {
            this.sql = string.Empty;
            this.sql = "UPDATE plust_factura SET ";
            this.sql += "fecha_emision = '";
            this.sql += factura.fecha_emision + "'";
            this.sql += ", estado_pago = '";
            this.sql += factura.estado_pago + "'";
            this.sql += ", valor_neto = '";
            this.sql += factura.valor_neto + "'";
            this.sql += ", id_cliente = '";
            this.sql += factura.id_cliente + "'";
            this.sql += ", observacion = '";
            this.sql += factura.observacion + "'";
            this.sql += " WHERE id_factura = '";
            this.sql += factura.id_factura + "'";
            this.sql += ";";

            try
            {
                this._bd.ejecutarSinRetorno(this.sql);
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return false;
            }
        }

        /// <summary>
        /// Función que retorna la lista con las facturas del sistema
        /// </summary>
        /// <returns>Lista con todas las facturas</returns>
        public DataTable obtenerFacturas()
        {
            DataTable dt = new DataTable();
            this.sql = string.Empty;
            this.sql = "SELECT v.id_venta,c.id_cliente,f.id_factura, f.fecha_emision, c.nombre, f.valor_neto ,(CASE WHEN f.estado_pago = 1 THEN  'pagada' ELSE 'impaga' END) as estado FROM plust_factura f,plust_cliente c,plust_venta v WHERE f.id_cliente = c.id_cliente  AND v.id_factura = f.id_factura AND v.tipo_venta = 2 ORDER BY f.fecha_emision DESC;";
            try
            {
                dt = this._bd.ejecutarConRetorno(this.sql);
                return dt;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return null;
            }
        }

        /// <summary>
        /// Función que retorna una factura en el sistema
        /// </summary>
        /// <param name="id_factura"></param>
        /// <returns>Factura si existe, null si no existe</returns>
        public DataTable obtenerFactura(int id_factura)
        {
            //Funcion que retorna la lista con las facturas en el sistema
            DataTable dt = new DataTable();
            this.sql = string.Empty;
            this.sql = "SELECT id_factura, fecha_emision, valor_neto, estado_pago, id_cliente FROM plust_factura WHERE id_factura = ";
            this.sql += id_factura;

            try
            {
                dt = this._bd.ejecutarConRetorno(this.sql);
                return dt;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return null;
            }
        }

        /// <summary>
        /// Retorna una objeto factura.
        /// </summary>
        /// <param name="id_factura"></param>
        /// <returns></returns>
        public Factura obtenerFacturaObjeto(int id_factura)
        {
            DataTable dt = new DataTable();
            Factura factura = new Factura();
            this.sql = string.Empty;
            this.sql = "SELECT id_factura, fecha_emision, estado_pago, valor_neto, id_cliente FROM plust_factura WHERE id_factura = ";
            this.sql += id_factura;

            try
            {
                dt = this._bd.ejecutarConRetorno(this.sql);
                factura.id_factura = int.Parse(dt.Rows[0][0].ToString());
                factura.fecha_emision = dt.Rows[0][1].ToString();
                factura.estado_pago = int.Parse(dt.Rows[0][2].ToString());
                factura.valor_neto = int.Parse(dt.Rows[0][3].ToString());
                return factura;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return null;
            }
        }

        /// <summary>
        /// retorna el id del la ultima factura ingresada al bd.
        /// </summary>
        /// <returns></returns>
        public int retornarIdUltimaFactura()
        {
            this.sql = string.Empty;
            this.sql = "SELECT id_factura FROM plust_factura ORDER BY id_factura DESC LIMIT 1";
            try
            {
                DataTable data = this._bd.ejecutarConRetorno(sql);
                if (data.Rows.Count == 1)
                {
                    return int.Parse(data.Rows[0][0].ToString());
                }
                return -1;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return -1;
            }
        }

        #endregion

        #region Usuarios
        /// <summary>
        /// Obtiene la passsword del usuario.
        /// </summary>
        /// <param name="usuario"></param>
        /// <returns></returns>
        public string obternerPasswordUsuario(string usuario)
        {
            this.sql = string.Empty;
            this.sql = "SELECT password FROM plust_usuario WHERE usuario = '" + usuario + "';";

            try
            {
                DataTable dtProducto = this._bd.ejecutarConRetorno(this.sql);
                if (dtProducto.Rows.Count < 1)
                {
                    return null;
                }

                return dtProducto.Rows[0][0].ToString();

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return null;
            }
        }

        #endregion

        #region Categoria

        /// <summary>
        /// Obtiene todas las categorias de sistema
        /// </summary>
        /// <returns></returns>
        public DataTable obtenerCategorias()
        {
            //Funcion que retorna la lista con los nombres de las categorias en el sistema
            DataTable dt = new DataTable();
            this.sql = string.Empty;
            this.sql = "SELECT id_categoria,nombre_categoria,descripcion_categoria FROM plust_categoria;";

            try
            {
                DataTable dtCategorias = this._bd.ejecutarConRetorno(this.sql);
                dt = dtCategorias;
                return dt;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return null;
            }
        }
        
        /// <summary>
        /// Ingresa una nueva categoria a la BD.
        /// </summary>
        /// <param name="categoria"></param>
        /// <returns></returns>
        public bool insertarCategoria(Categoria categoria)
        {
            //Funcion que inserta una nueva categoria a la base de datos
            this.sql = string.Empty;
            this.sql += "INSERT INTO plust_categoria";
            this.sql += "(nombre_categoria, descripcion_categoria) ";
            this.sql += "values ('";
            this.sql += categoria.nombre_categoria;
            this.sql += "','";
            this.sql += categoria.descripcion_categoria;
            this.sql += "');";

            try
            {
                this._bd.ejecutarSinRetorno(this.sql);
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return false;
            }
        }

        /// <summary>
        /// Elimina un categoria.
        /// </summary>
        /// <param name="id_categoria"></param>
        /// <returns></returns>
        public bool eliminarCategoria(String id_categoria)
        {
            if(int.Parse(id_categoria) != 1)
            {
                this.sql = string.Empty;
                this.sql = "UPDATE plust_producto SET ";
                this.sql += "id_categoria = '1'";
                this.sql += " WHERE id_categoria = '";
                this.sql += id_categoria + "'";
                this.sql += ";";

                try
                {
                    this._bd.ejecutarSinRetorno(this.sql);

                    this.sql = string.Empty;
                    this.sql = "DELETE FROM plust_categoria WHERE id_categoria = '" + id_categoria + "';";

                    this._bd.ejecutarSinRetorno(this.sql);

                    return true;
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                    return false;
                }
            }
            else
            {
                return false;
            }
        }
        
        /// <summary>
        /// Verifica si una categoria existe.
        /// </summary>
        /// <param name="nombre_categoria"></param>
        /// <returns></returns>
        public bool existeCategoria(String nombre_categoria)
        {
            //Funcion que indica si una categoria existe en el sistema
            this.sql = string.Empty;
            this.sql = "SELECT COUNT(*) FROM plust_categoria WHERE nombre_categoria = '" + nombre_categoria + "';";
            try
            {
                DataTable dtResultado = this._bd.ejecutarConRetorno(this.sql);
                int cantidad = int.Parse(dtResultado.Rows[0][0].ToString());
                if (cantidad == 0)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return true;
            }
        }

        /// <summary>
        /// Actualiza una categoria.
        /// </summary>
        /// <param name="categoria"></param>
        /// <returns></returns>
        public bool actualizarCategoria(Categoria categoria)
        {
            this.sql = string.Empty;
            this.sql = "UPDATE plust_categoria SET ";
            this.sql += "nombre_categoria = '";
            this.sql += categoria.nombre_categoria + "'";
            this.sql += ", descripcion_categoria = '";
            this.sql += categoria.descripcion_categoria + "'";
            this.sql += " WHERE id_categoria = '";
            this.sql += categoria.id_categoria + "'";
            this.sql += ";";

            try
            {
                this._bd.ejecutarSinRetorno(this.sql);
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return false;
            }
        }
        #endregion categoria

        #region productos

        /// <summary>
        /// Obtiene todos los productos de la bd.
        /// </summary>
        /// <returns></returns>
        public DataTable obtenerProductos()
        {
            this.sql = string.Empty;
            this.sql = "SELECT id_producto, sku, descripcion, fecha_creacion, precio_neto, precio_venta, stock_critico, stock_real, id_categoria FROM plust_producto WHERE estado = 'activo';";

            try
            {
                return this._bd.ejecutarConRetorno(this.sql);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return null;
            }
        }

        /// <summary>
        /// Retorna todos los productos para el reporte excel.
        /// </summary>
        /// <returns></returns>
        public DataTable obtenerProductosReporte()
        {
            this.sql = string.Empty;
            this.sql = "SELECT id_producto, sku, descripcion, fecha_creacion, precio_neto, precio_venta, stock_critico, stock_real, c.nombre_categoria " +
                       "FROM plust_producto p, plust_categoria c " +
                       "WHERE p.id_categoria = c.id_categoria AND p.estado = 'activo'";

            try
            {
                return this._bd.ejecutarConRetorno(this.sql);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return null;
            }
        }

        /// <summary>
        /// Obtiene un cliente dado el sku.
        /// </summary>
        /// <param name="sku"></param>
        /// <returns></returns>
        public Producto obtenerProductoSku(String sku)
        {
            this.sql = string.Empty;
            this.sql = "SELECT id_producto, sku, descripcion, fecha_creacion, precio_neto, precio_venta, stock_critico, stock_real, id_categoria FROM plust_producto WHERE sku = '" + sku + "' AND estado = 'activo';";

            try
            {
                DataTable dtProducto = this._bd.ejecutarConRetorno(this.sql);
                if (dtProducto.Rows.Count < 1)
                {
                    //Si no existe el sku, no existe el producto
                    return null;
                }
                else
                {
                    //Se crea un nuevo producto
                    Producto producto = new Producto();
                    //Se asignan los valores para los atributos
                    producto.id_producto = int.Parse(dtProducto.Rows[0][0].ToString());
                    producto.sku = dtProducto.Rows[0][1].ToString();
                    producto.descripcion = dtProducto.Rows[0][2].ToString();
                    producto.fecha_creacion = dtProducto.Rows[0][3].ToString();
                    producto.precio_neto = int.Parse(dtProducto.Rows[0][4].ToString());
                    producto.precio_venta = int.Parse(dtProducto.Rows[0][5].ToString());
                    producto.stock_critico = int.Parse(dtProducto.Rows[0][6].ToString());
                    producto.stock_real = int.Parse(dtProducto.Rows[0][7].ToString());
                    producto.id_categoria = int.Parse(dtProducto.Rows[0][8].ToString());
                    //Se retorna el producto obtenido
                    return producto;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return null;
            }
        }

        /// <summary>
        /// Obtiene un producto dado el id del producto.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Producto obtenerProductoId(String id)
        {
            this.sql = string.Empty;
            this.sql = "SELECT id_producto, sku, descripcion, fecha_creacion, precio_neto, precio_venta, stock_critico, stock_real, id_categoria FROM plust_producto WHERE id_producto = '" + id + "' AND estado = 'activo';";

            try
            {
                DataTable dtProducto = this._bd.ejecutarConRetorno(this.sql);
                if (dtProducto.Rows.Count < 1)
                {
                    //Si no existe el sku, no existe el producto
                    return null;
                }
                //Se crea un nuevo producto
                Producto producto = new Producto();
                //Se asignan los valores para los atributos
                producto.id_producto = int.Parse(dtProducto.Rows[0][0].ToString());
                producto.sku = dtProducto.Rows[1][0].ToString();
                producto.descripcion = dtProducto.Rows[1][0].ToString();
                producto.fecha_creacion = dtProducto.Rows[2][0].ToString();
                producto.precio_neto = int.Parse(dtProducto.Rows[3][0].ToString());
                producto.precio_venta = int.Parse(dtProducto.Rows[4][0].ToString());
                producto.stock_critico = int.Parse(dtProducto.Rows[5][0].ToString());
                producto.stock_real = int.Parse(dtProducto.Rows[6][0].ToString());
                producto.id_categoria = int.Parse(dtProducto.Rows[7][0].ToString());
                //Se retorna el producto obtenido
                return producto;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return null;
            }
        }
        
        /// <summary>
        /// Obtiene los productos que coincidan con la descripción.
        /// </summary>
        /// <param name="descripcion"></param>
        /// <returns></returns>
        public DataTable obtenerProductosDescripcion(String descripcion)
        {
            this.sql = string.Empty;
            this.sql = "SELECT sku, descripcion, precio_venta, stock_real FROM plust_producto WHERE descripcion LIKE '%" + descripcion + "%' AND estado = 'activo';";

            try
            {
                DataTable dtProductos = this._bd.ejecutarConRetorno(this.sql);
                return dtProductos;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return null;
            }
        }

        /// <summary>
        /// Obtiene los productos con stock critico.
        /// </summary>
        /// <returns></returns>
        public DataTable obtenerProductosStockCritico()
        {
            this.sql = string.Empty;
            this.sql = "SELECT Producto.id_producto, Producto.sku, Producto.descripcion, Producto.fecha_creacion, Producto.precio_neto, Producto.precio_venta, Producto.stock_critico, Producto.stock_real, Categoria.nombre_categoria FROM plust_producto Producto, plust_categoria Categoria WHERE Producto.id_categoria = Categoria.id_categoria AND Producto.stock_real <= Producto.stock_critico AND Producto.estado = 'activo';";

            try
            {
                DataTable dtProductos = this._bd.ejecutarConRetorno(this.sql);
                return dtProductos;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return null;
            }
        }

        /// <summary>
        /// Ingresa un nuevo producto
        /// </summary>
        /// <param name="nuevo"></param>
        /// <returns></returns>
        public bool ingresarNuevoProducto(Producto nuevo)
        {
            this.sql = string.Empty;
            this.sql += "INSERT INTO plust_producto";
            this.sql += "(sku,descripcion,fecha_creacion,precio_neto,precio_venta,stock_critico,stock_real,id_categoria,estado) ";
            this.sql += "values ('";
            this.sql += nuevo.sku;
            this.sql += "','";
            this.sql += nuevo.descripcion;
            this.sql += "','";
            this.sql += DateTime.Now.ToString();
            this.sql += "',";
            this.sql += nuevo.precio_neto;
            this.sql += ",";
            this.sql += nuevo.precio_venta;
            this.sql += ",";
            this.sql += nuevo.stock_critico;
            this.sql += ",";
            this.sql += nuevo.stock_real;
            this.sql += ",";
            this.sql += nuevo.id_categoria;
            this.sql += ",'";
            this.sql += "activo";
            this.sql += "');";

            try
            {
                this._bd.ejecutarSinRetorno(this.sql);
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return false;
            }
        }

        /// <summary>
        /// Inactiva un producto.
        /// </summary>
        /// <param name="id_producto"></param>
        /// <returns></returns>
        public bool eliminarProducto(String id_producto)
        {
            //Funcion que elimina una categoria de la base de datos
            this.sql = string.Empty;
            this.sql = "UPDATE plust_producto SET estado = 'inactivo' WHERE id_producto = '" + id_producto + "';";

            try
            {
                this._bd.ejecutarSinRetorno(this.sql);
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return false;
            }
        }
        
        /// <summary>
        /// Verifica si el producto existe dado el sku.
        /// </summary>
        /// <param name="sku"></param>
        /// <returns></returns>
        public bool existeProductoSku(String sku)
        {
            //Funcion que indica si un producto existe en el sistema
            this.sql = string.Empty;
            this.sql = "SELECT COUNT(*) FROM plust_producto WHERE sku = '" + sku + "' AND estado = 'activo';";
            try
            {
                DataTable dtResultado = this._bd.ejecutarConRetorno(this.sql);
                int cantidad = int.Parse(dtResultado.Rows[0][0].ToString());
                if (cantidad == 0)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return false;
            }
        }

        /// <summary>
        /// Verifica si existe una producto dado el id.
        /// </summary>
        /// <param name="id_producto"></param>
        /// <returns></returns>
        public bool existeProductoId(String id_producto)
        {
            //Funcion que indica si un producto existe en el sistema
            this.sql = string.Empty;
            this.sql = "SELECT COUNT(*) FROM plust_producto WHERE id_producto = '" + id_producto + "' AND estado = 'activo';";
            try
            {
                DataTable dtResultado = this._bd.ejecutarConRetorno(this.sql);
                int cantidad = int.Parse(dtResultado.Rows[0][0].ToString());
                if (cantidad == 0)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return false;
            }
        }

        /// <summary>
        /// Actualiza un producto.
        /// </summary>
        /// <param name="producto"></param>
        /// <returns></returns>
        public bool actualizarProducto(Producto producto)
        {
            this.sql = string.Empty;
            this.sql = "UPDATE plust_producto SET ";
            this.sql += "sku='";
            this.sql += producto.sku + "'";
            this.sql += ",precio_neto='";
            this.sql += producto.precio_neto.ToString() + "'";
            this.sql += ",precio_venta='";
            this.sql += producto.precio_venta.ToString() + "'";
            this.sql += ",stock_critico='";
            this.sql += producto.stock_critico.ToString() + "'";
            this.sql += ",stock_real='";
            this.sql += producto.stock_real.ToString() + "'";
            this.sql += ",descripcion='";
            this.sql += producto.descripcion + "'";
            this.sql += ",id_categoria='";
            this.sql += producto.id_categoria + "'";
            this.sql += " WHERE id_producto='";
            this.sql += producto.id_producto.ToString() + "'";
            this.sql += ";";

            try
            {
                this._bd.ejecutarSinRetorno(this.sql);
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return false;
            }
        }

        /// <summary>
        /// Función que retorna el valor del stock actual del producto con id "id_producto".
        /// </summary>
        /// <param name="id_producto"></param>
        /// <returns></returns>
        public int obtenerStockReal(String id_producto)
        {
            this.sql = string.Empty;
            this.sql = "SELECT stock_real FROM plust_producto WHERE id_producto = '" + id_producto + "';";
            Debug.WriteLine(sql);

            try
            {
                DataTable dtResultado = this._bd.ejecutarConRetorno(this.sql);
                int stock_real = int.Parse(dtResultado.Rows[0][0].ToString());
                Debug.WriteLine(stock_real);
                return stock_real;

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return -1;
            }
        }

        
        /// <summary>
        /// Funcion que actualiza el stock actual en "stock_nuevo" de un producto con id "id_producto".
        /// </summary>
        /// <param name="id_producto"></param>
        /// <param name="stock_nuevo"></param>
        /// <returns></returns>
        public bool actualizarStockReal(String id_producto, int stock_nuevo)
        {
            this.sql = string.Empty;
            this.sql = "UPDATE plust_producto SET ";
            this.sql += "stock_real = '" + stock_nuevo.ToString() + "' ";
            this.sql += "WHERE id_producto = '" + id_producto + "';";

            try
            {
                this._bd.ejecutarSinRetorno(this.sql);
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return false;
            }
        }

        /// <summary>
        /// Función que rebaja "cantidad" en el stock del producto con id "id_producto".
        /// </summary>
        /// <param name="id_producto"></param>
        /// <param name="cantidad"></param>
        /// <returns></returns>
        public bool rebajarStock(String id_producto, int cantidad)
        {
            int stock_real = obtenerStockReal(id_producto);
            /*
            if(stock_real < 0)
            {
                Debug.WriteLine("El producto no existe o existe un problema al obtener el stock real");
                return false;
            }
            */
            int stock_nuevo = stock_real - cantidad;
            Debug.WriteLine("stockreal" + stock_real);
            Debug.WriteLine("cantidad" + cantidad);
            Debug.WriteLine("stocknuevo" + stock_nuevo);
            if (actualizarStockReal(id_producto, stock_nuevo))
            {
                return true;
            }
            else
            {
                Debug.WriteLine("Error a intentar rebajar el stock");
                return false;
            }
        }

        #endregion

        #region ventas

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Boolean vincularVenta()
        {
            int id_venta = this.retornarIdUltimaVenta();
            int id_factura = this.retornarIdUltimaFactura();
            this.sql = string.Empty;
            this.sql = "UPDATE plust_venta SET id_factura = ";
            this.sql += id_factura;
            this.sql += " WHERE id_venta = ";
            this.sql += id_venta;

            try
            {
                this._bd.ejecutarSinRetorno(sql);
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return false;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="v"></param>
        public void rebajarStockVenta(Venta v)
        {
            List<Producto> lp = v.listaProd;
            List<int> lc = v.listaCant;

            for (int i = 0; i < lp.Count; i++)
            {
                Debug.WriteLine("{" + lp[i].id_producto.ToString() + "," + lc[i] + "}");
                this.rebajarStock(lp[i].id_producto.ToString(), lc[i]);
            }
        }

        /// <summary>
        /// Obtener todas las ventas
        /// </summary>
        /// <returns></returns>
        public DataTable obtenerVentas()
        {
            this.sql = string.Empty;
            this.sql = "SELECT id_venta, fecha_venta,monto_venta,CASE WHEN tipo_venta = 1 THEN 'Boleta' ELSE CASE WHEN tipo_venta = 2 THEN 'Factura' ELSE 'Ninguno' END END as tipo_vta,tipo_venta,id_factura,id_boleta FROM plust_venta ORDER BY fecha_venta DESC";
            try
            {
                return this._bd.ejecutarConRetorno(this.sql);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return null;
            }
        }

        /// <summary>
        /// Elimina una venta.
        /// </summary>
        /// <param name="id_venta"></param>
        /// <returns></returns>
        public bool eliminarVenta(String id_venta)
        {
            //Funcion que elimina una categoria de la base de datos
            this.sql = string.Empty;
            this.sql = "DELETE FROM plust_venta WHERE id_venta = '" + id_venta + "';";

            try
            {
                this._bd.ejecutarSinRetorno(this.sql);
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return false;
            }
        }

        /// <summary>
        /// Ingresar nueva venta.
        /// </summary>
        /// <param name="venta"></param>
        /// <returns></returns>
        public bool ingresarNuevaVenta(Venta venta)
        {
            this.sql = string.Empty;
            this.sql += "INSERT INTO plust_venta";
            this.sql += "(fecha_venta,monto_venta,tipo_venta,id_factura,id_boleta) ";
            this.sql += "values ('";
            this.sql += DateTime.Now.ToString();
            this.sql += "',";
            this.sql += venta.monto_venta;
            this.sql += ",";
            this.sql += venta.tipo_venta;
            this.sql += ",";
            this.sql += venta.id_factura;
            this.sql += ",";
            this.sql += venta.id_boleta;
            this.sql += ");";

            try
            {
                this._bd.ejecutarSinRetorno(sql);
                this.ingresarProdVenta(venta);
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return false;
            }
        }

        /// <summary>
        /// Ingresar los productos a la venta.
        /// </summary>
        /// <param name="venta"></param>
        /// <returns></returns>
        public bool ingresarProdVenta(Venta venta)
        {
            int id_venta = this.retornarIdUltimaVenta();
            if (id_venta != -1)
            {
                for (int i = 0; i < venta.listaProd.Count; i++)
                {
                    int id_prod = venta.listaProd[i].id_producto;
                    int cant = venta.listaCant[i];
                    int valor = venta.listaProd[i].precio_venta;
                    this.ingresarProdAVenta(id_venta, id_prod, cant,valor);
                    Debug.WriteLine("ingresando id_prod " + id_prod + " a venta");
                }
            }
            return false;
        }

        /// <summary>
        /// Guarda los productos de la venta en bd.
        /// </summary>
        /// <param name="id_vta"></param>
        /// <param name="id_prod"></param>
        /// <param name="cant"></param>
        /// <param name="valor"></param>
        /// <returns></returns>
        private bool ingresarProdAVenta(int id_vta, int id_prod, int cant,int valor)
        {
            this.sql = string.Empty;
            this.sql += "INSERT INTO plust_prodxventa";
            this.sql += "(id_venta,id_producto,cantidad,valor) ";
            this.sql += "values (";
            this.sql += id_vta;
            this.sql += ",";
            this.sql += id_prod;
            this.sql += ",";
            this.sql += cant;
            this.sql += ",";
            this.sql += valor;
            this.sql += ");";

            Debug.WriteLine(this.sql);
            try
            {
                this._bd.ejecutarSinRetorno(sql);
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return false;
            }
        }

        public int retornarIdUltimaVenta()
        {
            this.sql = string.Empty;
            this.sql = "SELECT id_venta FROM plust_venta ORDER BY id_venta DESC LIMIT 1";
            try
            {
                DataTable data = this._bd.ejecutarConRetorno(sql);
                if (data.Rows.Count == 1)
                {
                    return int.Parse(data.Rows[0][0].ToString());
                }
                return -1;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return -1;
            }
        }

        public DataTable retornarProdxVenta(int id_venta)
        {
            this.sql = string.Empty;
            this.sql = "SELECT  p.descripcion as Producto,x.valor as Precio,x.cantidad as Cantidad, (x.valor * x.cantidad) as Total "
                      + "FROM plust_prodxventa x, plust_producto p, plust_venta v "
                      + "WHERE x.id_venta = v.id_venta "
                      + "AND x.id_producto = p.id_producto "
                      + "AND v.id_venta =";
            this.sql += id_venta;
            this.sql += ";";
            try
            {
                return this._bd.ejecutarConRetorno(sql);

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return null;
            }
        }

        #endregion

        #region Pago

        public int retornarTotalPagos(int id_factura)
        {
            this.sql = string.Empty;
            this.sql = "select  sum(monto_pago) as total_pago from plust_pago where id_factura = ";
            this.sql += id_factura;
            try
            {
                DataTable data = this._bd.ejecutarConRetorno(sql);
                if (data.Rows.Count == 1)
                {
                    return int.Parse(data.Rows[0][0].ToString());
                }
                return -1;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return -1;
            }
        }

        //Ingreso de un pago
        public Boolean generarPago(Pago pago)
        {
            this.sql = string.Empty;
            this.sql = "INSERT INTO plust_pago(tipo_pago,fecha_pago,monto_pago,descripcion,id_factura) VALUES ('";
            this.sql += pago.tipo_pago;
            this.sql += "','";
            this.sql += pago.fecha_pago;
            this.sql += "','";
            this.sql += pago.monto_pago;
            this.sql += "','";
            this.sql += pago.descripcion;
            this.sql += "',";
            this.sql += pago.id_factura;
            this.sql += ")";

            try
            {
                this._bd.ejecutarSinRetorno(sql);
                this.verificarEstadoPago(pago.id_factura);
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return false;
            }
        }

        public DataTable obternerPagos(string id_factura)
        {
            this.sql = string.Empty;
            this.sql = "SELECT tipo_pago,descripcion,fecha_pago,monto_pago FROM plust_pago WHERE id_factura='" + id_factura + "';";

            try
            {
                return this._bd.ejecutarConRetorno(sql);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return null;
            }
        }

        //Verificacion de estado de factura 'paga' o 'impaga'
        public Boolean verificarEstadoPago(int id_factura)
        {
            int suma_pagos = this.retornarTotalPagos(id_factura);
            Factura fact = this.obtenerFacturaObjeto(id_factura);
            Debug.WriteLine("fact: " + fact.valor_neto);
            int valor_fact = Convert.ToInt32(fact.valor_neto * 1.19);

            if (suma_pagos >= valor_fact)
            {
                Debug.WriteLine("sumapago: " + suma_pagos + "-valor_fact: " + valor_fact);
                this.sql = string.Empty;
                this.sql = "UPDATE plust_factura SET estado_pago = 1 WHERE id_factura = ";
                this.sql += id_factura; 

                try
                {
                    this._bd.ejecutarSinRetorno(sql);
                    return true;
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                    return false;
                }
            }
            else
            {
                return false;
            }
        }

        #endregion

        #region Cliente

        public int retornarIdUltimoCliente()
        {
            this.sql = string.Empty;
            this.sql = "SELECT id_cliente FROM plust_cliente ORDER BY id_cliente DESC LIMIT 1";
            try
            {
                DataTable data = this._bd.ejecutarConRetorno(sql);
                if (data.Rows.Count == 1)
                {
                    return int.Parse(data.Rows[0][0].ToString());
                }
                return -1;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return -1;
            }
        }

        public Cliente obtenerCliente(string id_cliente)
        {
            this.sql = string.Empty;
            this.sql = "SELECT id_cliente,nombre, rut, giro, direccion, ciudad, comuna FROM plust_cliente WHERE id_cliente = '" + id_cliente + "';";

            try
            {
                DataTable dtCliente = this._bd.ejecutarConRetorno(this.sql);
                if (dtCliente.Rows.Count < 1)
                {

                    return null;
                }
                else
                {

                    Cliente cliente = new Cliente();

                    cliente.id_cliente = int.Parse(dtCliente.Rows[0][0].ToString());
                    cliente.nombre = dtCliente.Rows[0][1].ToString();
                    cliente.rut = dtCliente.Rows[0][2].ToString();
                    cliente.giro = dtCliente.Rows[0][3].ToString();
                    cliente.direccion = dtCliente.Rows[0][4].ToString();
                    cliente.ciudad = dtCliente.Rows[0][5].ToString();
                    cliente.comuna = dtCliente.Rows[0][6].ToString();

                    return cliente;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return null;
            }
        }

        public bool eliminarCliente(String id_cliente)
        {
            this.sql = string.Empty;
            this.sql = "DELETE FROM plust_cliente WHERE id_cliente = '" + id_cliente + "';";

            try
            {
                this._bd.ejecutarSinRetorno(this.sql);
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return false;
            }
        }

        public DataTable getCliente(String id_cliente)
        {
            this.sql = string.Empty;
            this.sql = "SELECT * FROM plust_cliente WHERE id_cliente = '" + id_cliente + "';";

            try
            {
                return this._bd.ejecutarConRetorno(this.sql);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return null;
            }
        }

        /// <summary>
        /// Actualiza un cliente en la BD.
        /// </summary>
        /// <param name="cliente"></param>
        /// <returns></returns>
        public bool actualizarCliente(Cliente cliente)
        {
            this.sql = string.Empty;
            this.sql = "UPDATE plust_cliente SET ";
            this.sql += "nombre = '";
            this.sql += cliente.nombre + "'";
            this.sql += ", rut = '";
            this.sql += cliente.rut + "'";
            this.sql += ", giro = '";
            this.sql += cliente.giro + "'";
            this.sql += ", direccion = '";
            this.sql += cliente.direccion + "'";
            this.sql += ", ciudad = '";
            this.sql += cliente.ciudad + "'";
            this.sql += ", comuna = '";
            this.sql += cliente.comuna + "'";
            this.sql += " WHERE id_cliente = '";
            this.sql += cliente.id_cliente + "'";
            this.sql += ";";

            try
            {
                this._bd.ejecutarSinRetorno(this.sql);
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return false;
            }
        }

        /// <summary>
        /// Obtiene todos los clientes de la DB.
        /// </summary>
        /// <returns></returns>
        public DataTable obternerClientes()
        {
            this.sql = string.Empty;
            this.sql = "SELECT id_cliente,nombre,rut,giro,direccion,comuna,ciudad FROM plust_cliente";

            try
            {
                return this._bd.ejecutarConRetorno(sql);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return null;
            }
        }

        //Retorna id_cliente,nombre,rut,giro,direccion,comuna,ciudad de un cliente
        public DataTable buscarCliente(String rut_cliente)
        {
            this.sql = string.Empty;
            this.sql = "SELECT id_cliente,nombre,rut,giro,direccion,comuna,ciudad FROM plust_cliente WHERE rut LIKE '";
            this.sql += rut_cliente;
            this.sql += "%'";
            try
            {
                return this._bd.ejecutarConRetorno(sql);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return null;
            }
        }

        //Retorna id_cliente,nombre,rut,giro,direccion,comuna,ciudad de un cliente
        public DataTable buscarClientesPorString(String buscado)
        {
            this.sql = string.Empty;
            this.sql = "SELECT c.id_cliente as id,c.nombre as nombre,c.rut as rut,c.giro as giro,c.direccion as direccion,c.comuna as comuna,c.ciudad as ciudad FROM plust_cliente c WHERE c.nombre LIKE '%";
            this.sql += buscado;
            this.sql += "%'";
            this.sql += " OR c.rut LIKE '%";
            this.sql += buscado;
            this.sql += "%';";

            try
            {
                return this._bd.ejecutarConRetorno(sql);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return null;
            }
        }

        //Ingreso de un cliente
        public Boolean ingresarCliente(Cliente cliente)
        {
            this.sql = string.Empty;
            this.sql = "INSERT INTO plust_cliente (nombre,rut,giro,direccion,comuna,ciudad) values ('";
            this.sql += cliente.nombre;
            this.sql += "','";
            this.sql += cliente.rut;
            this.sql += "','";
            this.sql += cliente.giro;
            this.sql += "','";
            this.sql += cliente.direccion;
            this.sql += "','";
            this.sql += cliente.comuna;
            this.sql += "','";
            this.sql += cliente.ciudad;
            this.sql += "')";

            try
            {
                this._bd.ejecutarSinRetorno(sql);
                return true;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return false;
            }
        }

        public bool existeCliente(String rut)
        {
            //Funcion que indica si una categoria existe en el sistema
            this.sql = string.Empty;
            this.sql = "SELECT COUNT(*) FROM plust_cliente WHERE rut = '" + rut + "';";
            try
            {
                DataTable dtResultado = this._bd.ejecutarConRetorno(this.sql);
                int cantidad = int.Parse(dtResultado.Rows[0][0].ToString());
                if (cantidad == 0)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return true;
            }
        }

        #endregion    

    }
}
